//
//  MYGNetwork.swift
//  MYGrow
//
//  Created by 小火科技 on 2024/2/29.
//

import Moya
import HandyJSON

fileprivate let provider = MoyaProvider<MultiTarget>()

protocol MYGTargetType: TargetType {
    var params: [String: Any] {get}
    var needToken: Bool { get }
    
    var isServer: Int { get }
}

extension MYGTargetType {
    var task: Moya.Task {
        var encoding: ParameterEncoding = URLEncoding.default
        switch self.method {
        case .post:
            encoding = JSONEncoding.default
        default:
            break
        }
        return .requestParameters(parameters: params, encoding: encoding)
    }
}

extension TargetType {
    var baseURL: URL {
        URL(string: BaseUrl)!
    }
    
    var headers: [String: String]? {
        var params: [String: String] = [:]
        params["Authorization"] = "Bearer c0ffS-pUxla8oTN-UoNhy6edIF8fR1T3_1705376542"
        if let user = MYGUserManager.user {
            params["Authorization"] = "Bearer \(user.verification_token)"
        }
        return params
    }
    var needToken: Bool {
        true
    }
    
    var isServer: Int {
        0
    }
    var task: Moya.Task {
        var encoding: ParameterEncoding = URLEncoding.default
        switch self.method {
        case .post:
            encoding = JSONEncoding.default
        default:
            break
        }
        
        return .requestParameters(parameters: params, encoding: encoding)
    }
    
    var params: [String: Any] {
        [:]
    }
}

class MYGNetwork<T: TargetType, Y: HandyJSON> {
    typealias ResultItem = Y
    typealias MYGSuccessBlock = (ResultItem) -> Void
    typealias MYGErrorBlock = (Int, String) -> Void
    typealias MYGProgressBlock = (Double) -> Void
    typealias MYGStringBlock = (String) -> Void

    
    static func request(target: T, success: @escaping MYGSuccessBlock, failed: @escaping MYGErrorBlock) {
        provider.request(MultiTarget(target)) { result in
            switch result {
            case let .success(data):
                let jsonMap = try? data.data.jsonObject()
                print("请求路径=\(target.path)\n  返回结果 = \(jsonMap ?? "")")
                print("请求传参：" + handleParams(task: "\(target.task)"))
                let json = String(data: data.data, encoding: .utf8)
                print("statusCode = \(data.statusCode)")
                guard let model = MYGBaseModel<Y>.deserialize(from: json) else {
                    failed(-1, "数据解析失败")
                    return
                }
                
                guard model.success else {
                    failed(-2, model.message)
                    return
                }
                success(model.data)
            case let .failure(error):
                failed(error.errorCode, error.localizedDescription)
            }
        }
    }
    //带进度请求
    static func upload(target: T, progressCallBack: MYGProgressBlock? = .none,success: @escaping MYGStringBlock, failed: @escaping MYGErrorBlock) {
        provider.request(MultiTarget(target),progress: { progress in
            if let callback = progressCallBack {
                callback(progress.progress)
            }
        }) { result in
            switch result {
            case let .success(data):
                let jsonMap = try? data.data.jsonObject()
                print("请求路径=\(target.path)\n  返回结果 = \(jsonMap ?? "")")
                print("请求传参：" + handleParams(task: "\(target.task)"))
                let json = String(data: data.data, encoding: .utf8)
                print("statusCode = \(data.statusCode)")
                guard let model = MYGBaseModel<Y>.deserialize(from: json) else {
                    failed(-1, "数据解析失败")
                    return
                }
                guard model.success else {
                    failed(-2, model.message)
                    return
                }
                if let text = model.stringData, !text.isEmpty {
                    success(text)
                }
            case let .failure(error):
                print("请求失败：error:\(error.localizedDescription)")
                failed(error.errorCode, error.localizedDescription)
            }
        }
    }
    
    
   static func handleParams(task:String) ->String{
        if task == "requestPlain" {
            return task
        }else{
           let result = task.components(separatedBy: "requestParameters(parameters:")
            if result.count > 1 {
                let params:String = result[1]
                return params.components(separatedBy: ", encoding:")[0]
            }
              return ""
        }
    }
}

class DennyNetwork {
    typealias MYGSuccessBlock<Y:HandyJSON> = (([Y]) -> Void)
    typealias MYGErrorBlock = (Int, String) -> Void
    
    static func request<Y: HandyJSON>(_ target: TargetType,
                                      modelType: [Y].Type,
                                      success: @escaping MYGSuccessBlock<Y>,
                                      failed: @escaping MYGErrorBlock) {
        
        provider.request(MultiTarget(target)) { result in
            switch result {
            case let .success(data):
                let jsonMap = try? data.data.jsonObject()
                print("请求路径=\(target.path)\n  返回结果 = \(jsonMap ?? "")")
                print("请求传参：" + handleParams(task: "\(target.task)"))
//                let json = String(data: data.data, encoding: .utf8)
                print("statusCode = \(data.statusCode)")
                if let jsonMap = try? data.data.jsonObject() as? Dictionary<String, Any> {
                    if  let result = jsonMap?["data"] as? [Any]{
                        print("\(result)")
                        let json = result.toJsonstring()
                        if let list = [Y].deserialize(from: json) {
                            var models = [Y]()
                            for m in list {
                                models.append(m ?? Y())
                            }
                            success(models)
                        }
                    }
                }
            case let .failure(error):
                failed(error.errorCode, error.localizedDescription)
            }
        }
    }
    static func handleParams(task:String) ->String{
         if task == "requestPlain" {
             return task
         }else{
            let result = task.components(separatedBy: "requestParameters(parameters:")
             if result.count > 1 {
                 let params:String = result[1]
                 return params.components(separatedBy: ", encoding:")[0]
             }
               return ""
         }
     }
}

class MMYGNetwork<T: MYGTargetType, Y: HandyJSON> {
    typealias ResultItem = Y
    typealias MYGSuccessBlock = (ResultItem?) -> Void
    typealias MYGSuccessStringBlock = (String) -> Void
    typealias MYGErrorBlock = (Int, String) -> Void
    
    static func request(target: T, success: @escaping MYGSuccessBlock, stringBlock: MYGSuccessStringBlock? = nil, failed: @escaping MYGErrorBlock) {
        provider.request(MultiTarget(target)) { result in
            switch result {
            case let .success(data):
                let str = String(data: data.data, encoding: .utf8)
                let jsonMap = try? data.data.jsonObject() as? Dictionary<String, Any>
                let json = String(data: data.data, encoding: .utf8)
                print("请求路径=\(target.path)\n  返回结果 = \(jsonMap)")
                print("请求传参：" + handleParams(task: "\(target.task)"))
                guard let model = MYGBaseModel<Y>.deserialize(from: json) else {
                    failed(-1, "数据解析失败")
                    return
                }
                print(target.path)
                guard ((model.success && (target.isServer == 0)) || (model.status == 200 && (target.isServer == 1)) || (model.code == 1 && (target.isServer == 2))) else {
                    failed(-2, model.message)
                    return
                }
                if target.path == "api/department/subject_all_list" || target.path == "/api/doctor/doctor_all_list" {
                    //科室
                    let yy:MYGSubjectListModel = MYGSubjectListModel.deserialize(from: json) ?? MYGSubjectListModel()
                    model.data = (yy as? Y)!
                }
                
                if target.path == "/api/micro/sys_messages/unread_num" {
                    // 消息未读
                    let yy:MYGMessageNumModel = MYGMessageNumModel.deserialize(from: json) ?? MYGMessageNumModel()
                    model.data = (yy as? Y)!
                }
                if target.path == "/api/schedule/get_month_schedule" {
                    // 日历
                    let yy:calenderListResponseModel = calenderListResponseModel.deserialize(from: json) ?? calenderListResponseModel()
                    model.data = (yy as? Y)!
                }
                if target.path == "/api/referral/notice"{
                    //系统消息
                    let yy:MYGMessageMessageListModel = MYGMessageMessageListModel.deserialize(from: json) ?? MYGMessageMessageListModel()
                    model.data = (yy as? Y)!
                }
                
                if target.path == "/api/community/my_answers" {
                    //我的回答
                    let yy:MYGCommunityModel = MYGCommunityModel.deserialize(from: json) ?? MYGCommunityModel()
                    model.data = (yy as? Y)!
                }
                if target.path == "/api/schedule/schedule"{
                    //日程
                    let yy:MYGScheduleBaseModel = MYGScheduleBaseModel.deserialize(from: json) ?? MYGScheduleBaseModel()
                    model.data = (yy as? Y)!
                }
                if target.path == "/api/community/doctor_follow_communities"{
                    //关注社群
                    let yy:MYGCommunityAllTypeModel = MYGCommunityAllTypeModel.deserialize(from: json) ?? MYGCommunityAllTypeModel()
                    model.data = (yy as? Y)!
                }
                
                
                success(model.data)
                if let text = model.stringData, !text.isEmpty {
                    stringBlock?(text)
                }
            case let .failure(error):
                failed(error.errorCode, error.localizedDescription)
            }
        }
    }
    static func handleParams(task:String) ->String{
         if task == "requestPlain" {
             return task
         }else{
            let result = task.components(separatedBy: "requestParameters(parameters:")
             if result.count > 1 {
                 let params:String = result[1]
                 return params.components(separatedBy: ", encoding:")[0]
             }
               return ""
         }
     }
}
